package com.iteaj.iboot.plugin.crawler.sites.buyin;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.iteaj.iboot.plugin.crawler.CrawlerProperties;
import com.iteaj.iboot.plugin.crawler.entity.SiteContent;
import com.iteaj.iboot.plugin.crawler.entity.SiteContentMedia;
import com.iteaj.iboot.plugin.crawler.entity.Sites;
import com.iteaj.iboot.plugin.crawler.service.ISiteContentService;
import com.iteaj.iboot.plugin.crawler.service.ISitesService;
import com.iteaj.iboot.plugin.crawler.sites.FetchMediaParam;
import com.iteaj.iboot.plugin.crawler.sites.SiteResolver;
import com.iteaj.iboot.plugin.crawler.sites.SiteResolverManager;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.io.File;

@Getter
@Setter
public abstract class SpringSiteResolverSupport implements SiteResolver, InitializingBean {

    private Sites sites;
    @Autowired
    private CrawlerProperties properties;
    @Autowired
    protected ISitesService sitesService;
    @Autowired
    private ThreadPoolTaskExecutor executor;
    @Autowired
    protected ISiteContentService siteContentService;
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void afterPropertiesSet() throws Exception {
        this.sites = sitesService
                .getOne(Wrappers.<Sites>lambdaQuery().eq(Sites::getAlias, getAlias()))
                .ifNotPresentThrow("站点不存在["+getAlias()+"]").getData();

        SiteResolverManager.registerResolver(this);
    }

    @Override
    public void fetchMedia(FetchMediaParam param) {
        executor.execute(() -> {
            if(CollectionUtil.isNotEmpty(param.getImages())) {
                try {
                    String localUri = properties.getCrawlerPath() + File.separator + param.getContentId() + File.separator + "image";
                    File file = new File(properties.getBasicPath() + localUri);
                    if(!file.exists()) {
                        file.mkdirs();
                    }

                    for (int i = 0; i < param.getImages().size(); i++) {
                        SiteContentMedia image = param.getImages().get(i);
                        if(StrUtil.isNotBlank(image.getUrl())) {
                            HttpResponse execute = HttpUtil.createGet(image.getCoverUrl()).execute();
                            String[] fileName = writeDataToFile(file, execute, i + 1);
                            if(fileName != null) {
                                siteContentService.updateMediaStatus(image.getId(), localUri + File.separator + fileName[0], SiteContentMedia.STATUS[1], fileName[1]);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("<<< 获取图片文件失败", e);
                }
            }

            if(CollectionUtil.isNotEmpty(param.getVideos())) {
                try {
                    String localUri = properties.getCrawlerPath() + File.separator + param.getContentId() + File.separator + "video";
                    File file = new File(properties.getBasicPath() + localUri);
                    if(!file.exists()) {
                        file.mkdirs();
                    }

                    for (int i = 0; i < param.getVideos().size(); i++) {
                        SiteContentMedia video = param.getVideos().get(i);
                        if(StrUtil.isNotBlank(video.getUrl())) {
                            HttpResponse execute = HttpUtil.createGet(video.getUrl()).execute();
                            String[] fileName = writeDataToFile(file, execute, i + 1);
                            if(fileName != null) {
                                siteContentService.updateMediaStatus(video.getId(), localUri + File.separator + fileName[0], SiteContentMedia.STATUS[2], fileName[1]);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("<<< 获取视频文件失败", e);
                }

            }

            if(CollectionUtil.isNotEmpty(param.getProducts())) {
                try {
                    String localUri = properties.getCrawlerPath() + File.separator + param.getContentId() + File.separator + "product";
                    File file = new File(properties.getBasicPath() + localUri);
                    if(!file.exists()) {
                        file.mkdirs();
                    }

                    for (int i = 0; i < param.getProducts().size(); i++) {
                        SiteContentMedia product = param.getProducts().get(i);
                        if(StrUtil.isNotBlank(product.getUrl())) {
                            HttpResponse execute = HttpUtil.createGet(product.getUrl()).execute();
                            String[] fileName = writeDataToFile(file, execute, i + 1);

                            if(fileName != null) {
                                siteContentService.updateMediaStatus(product.getId(), localUri + File.separator + fileName[0], SiteContentMedia.STATUS[2], fileName[1]);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("<<< 获取产品图片失败", e);
                }
            }

            Long count = siteContentService.countMedia(param.getContentId());
            if(count > 0) {
                siteContentService.removeMediaByLocalUrlIsNull(param.getContentId());
                siteContentService.updateStatus(param.getContentId(), SiteContent.STATUS[2]);
            } else {
                siteContentService.removeContentAndMedia(param.getContentId());
            }
        });
    }

    private String[] writeDataToFile(File parent, HttpResponse execute, int index) {
        String contentType = execute.header("Content-Type");
        if(execute.isOk() && execute.bodyBytes() != null && execute.bodyBytes().length > 0) {
            String[] split = contentType.split("/");
            if(split.length == 2) {
                String fileName = split[0] + String.format("%02d", index) + "." + split[1];
                File writeFile = new File(parent, fileName);
                FileUtil.writeBytes(execute.bodyBytes(), writeFile);
                return new String[] {fileName, split[0]};
            } else {
                logger.error("<<< 采集媒体文件失败 未知的媒体类型: {}", contentType);
            }
        } else {
            logger.error("<<< 采集媒体文件失败 状态码: {}", execute.getStatus());
        }

        return null;
    }

    protected void seleniumProcessInfoLog(String siteName, String steps, String desc, String... other) {
        logger.info("<<< Selenium操作({}) - 步骤: {} - 说明: {}", siteName, steps, desc);
    }

    protected void seleniumProcessWarnLog(String siteName, String steps, String desc, String... other) {
        logger.warn("<<< Selenium操作({}) - 步骤: {} - 说明: {}", siteName, steps, desc);
    }
}
